#include "tcp_server.h"
#include <iostream>
// Add Boost
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/filesystem.hpp>

using namespace std;
using namespace boost::property_tree;

//unsigned char bat = 100;
struct InterFaceInfo soldierOneInfo;
extern vector<string> gl_code_list;
extern int gl_patrol_num;
extern int gl_sentry_num;
const char* stateCode[14] = {"S00","S01","S02","S03","S04","E00","E01","E02","E03","E04","E05","E06","E07","E08"};
void listener_cb(evconnlistener *listener, evutil_socket_t fd,    
                 struct sockaddr *sock, int socklen, void *arg);    
    
void socket_read_cb(bufferevent *bev, void *arg);    
void socket_event_cb(bufferevent *bev, short events, void *arg);

string set_info_json(int battery, int lx, int ly, vector<string> &code_list, int patrol_num, int sentry_num)
{
    ptree pt_rsp_info, pt_child_code, pt_child_temp;

    vector<string>::iterator it;
    for (it = code_list.begin(); it != code_list.end(); ++it)
    {
        pt_child_temp.put("", *it);
        pt_child_code.push_back(make_pair("", pt_child_temp));            
    }

    pt_rsp_info.put<string>("server", "information");
    pt_rsp_info.put<int>("battery", battery);
    pt_rsp_info.put<int>("lx", lx);
    pt_rsp_info.put<int>("ly", ly);
    pt_rsp_info.put_child("code", pt_child_code);
    pt_rsp_info.put<int>("patrol_number", patrol_num);
    pt_rsp_info.put<int>("sentry_number", sentry_num);

    stringstream ss;
    write_json(ss, pt_rsp_info);

    return (ss.str());
}

void socket_info()    
{
    struct sockaddr_in sin;    
    memset(&sin, 0, sizeof(struct sockaddr_in));    
    sin.sin_family = AF_INET;    
    sin.sin_port = htons(9998);    
    
    event_base *base = event_base_new();    
    evconnlistener *listener    
            = evconnlistener_new_bind(base, listener_cb, base,    
                                      LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC,    
                                      10, (struct sockaddr*)&sin,    
                                      sizeof(struct sockaddr_in));    
    
    event_base_dispatch(base);    
    
    evconnlistener_free(listener);    
    event_base_free(base);    
}    

void listener_cb(evconnlistener *listener, evutil_socket_t fd,    
                 struct sockaddr *sock, int socklen, void *arg)    
{    
    printf("accept a client %d\n", fd);    
    
    event_base *base = (event_base*)arg;    
      
    bufferevent *bev =  bufferevent_socket_new(base, fd,    
                                               BEV_OPT_CLOSE_ON_FREE);    
    
    bufferevent_setcb(bev, socket_read_cb, NULL, socket_event_cb, NULL);    
    bufferevent_enable(bev, EV_READ | EV_PERSIST);    
}    
    
    
void socket_read_cb(bufferevent *bev, void *arg)    
{    
    char msg[1024] = {0};  
    size_t len = bufferevent_read(bev, msg, sizeof(msg));
    stringstream content(msg);

    try
    {
        ptree pt_client;
        read_json(content, pt_client);
        string server = pt_client.get<string>("server");
        //cout << "server: " << server << endl;

        if (server == "head_control")
        {
            // 头部运动模式: forward, shake, left, right
            string head = pt_client.get<string>("head");
			if(head == "forward")
				soldierOneInfo.headControl = 'f';
			else if(head == "left")
				soldierOneInfo.headControl = 'l';
			else if(head == "right")
				soldierOneInfo.headControl = 'r';
			else
				soldierOneInfo.headControl = 'n';
//            cout << "head: " << head << endl;
        }
        else if (server == "motion")
        {
            string task_mode = pt_client.get<string>("task_mode");
            int position = pt_client.get<int>("position");
            soldierOneInfo.slot = position;
//	    cout<<"slot:"<<soldierOneInfo.slot<<endl;
	    if(task_mode == "patrol")
	    {				
	 	soldierOneInfo.taskClass = PATROL;
            	soldierOneInfo.slot = position-1;
	    }
	    else
	    {
                soldierOneInfo.slot = position+gl_patrol_num-1;
		soldierOneInfo.taskClass = SENTRY;
	     }
   
//            cout << "task_mode: " << task_mode << endl;
//            cout << "position: " << position << endl;
	    soldierOneInfo.begin = 1;
        }
        else if (server == "information")
        {
            string rsp = set_info_json(soldierOneInfo.batteryCapacity, soldierOneInfo.lX, soldierOneInfo.lY, gl_code_list, gl_patrol_num, gl_sentry_num);            
            bufferevent_write(bev, rsp.c_str(), rsp.length());
        }
        else
        {
            cout << "Error: Invalid command!" << endl;
        }

    }
    catch (...)    
    {
        cout << "Error: read json from tcp client failed!" << endl;
    }

    //cout << "---------------------" << endl;
}    
    
    
void socket_event_cb(bufferevent *bev, short events, void *arg)    
{    
    if (events & BEV_EVENT_EOF)    
        printf("connection closed\n");    
    else if (events & BEV_EVENT_ERROR)    
        printf("some other error\n");    
    
    bufferevent_free(bev);    
}    
